package de.umr.fb12.vs.os.uebung;

import static de.umr.fb12.vs.os.Task.STATES.BLOCKED;
import static de.umr.fb12.vs.os.Task.STATES.DEAD;

import java.util.LinkedList;

import de.umr.fb12.vs.os.CoreScheduler;
import de.umr.fb12.vs.os.SchedClass;
import de.umr.fb12.vs.os.Task;

public class FifoSched implements SchedClass {

	// with this data structure we have a queue in where the first incoming task is 
	// the next selected task.
	private LinkedList<Task> run_q = new LinkedList<Task>();
	
	//start time of a task
	@SuppressWarnings("unused")
	private long start_time = 0;
	
	// if a task is the idle task then the task should be rescheduled to start the
	// enqueued task
	@Override
	public void enqueue_task(Task curr, Task enq) {
		if (curr.isIdle_task())
			curr.set_tsk_need_resched();
		run_q.addLast(enq);
	}

	// to remove a task, we should remove it from the run queue and reschedule again
	@Override
	public void dequeue_task(Task curr, Task deq) {
		if (curr == deq)
			curr.set_tsk_need_resched();
		// remove deq from the runqueue note: if curr==deq nothing happens
		run_q.remove(deq);
	}

	// this method yield a task
	@Override
	public void yield_task(Task curr, Task t) {
		if (curr == t)
			t.set_tsk_need_resched();
	}

	// the first incoming task is the next outgoing task
	@Override
	public Task pick_next_task() {
		Task next = null;
		if (run_q.size() > 0) {
			start_time = System.currentTimeMillis();
			next = run_q.remove(0);
		}
		return next;
	}

	// if the previous task is not dead or blocked, we put the task back
	// to the run queue
	@Override
	public void put_prev_task(Task prev) {
		if (prev.getState() != BLOCKED && prev.getState() != DEAD) {
			run_q.addLast(prev);
		}
	}

	// if a task is blocked or dead we need a reschedule act
	@Override
	public void task_tick(Task curr) {
		if(curr.getSchedclass() == this&&(curr.getState()==BLOCKED || curr.getState()==DEAD))
			curr.set_tsk_need_resched();
			
			
	}

	// a new task comes to the back of the queue
	@Override
	public void task_new(Task curr, Task newtsk) {
		run_q.addLast(newtsk);
	}

	public static void main(String[] args) {
		FifoSched fifoSched = new FifoSched();
		CoreScheduler.init(fifoSched, "asm/simple_init.asm",
				"asm/simple_dummy.asm");
	}
}
